/* Includes ------------------------------------------------------------------*/
#include <string.h>

#include "nsal.h"
#include "nril.h"
#include "rilConfig.h"
/* typedef -------------------------------------------------------------------*/
struct Socket *_socketList[RIL_MAX_SOCKET_COUNT] = {0};
/* define --------------------------------------------------------------------*/
#define GET_SOCKET(id)  getsocket(id)

/* macro ---------------------------------------------------------------------*/
/* variables -----------------------------------------------------------------*/
extern struct RilDevice _rilDevice;
/* function prototypes -------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/
/*********************************************************************************************

  * @brief  socket
  * @param  domain      
            type        
            protocol    
  * @return >=0, the socket id
            <0, error code
  * @remark create a new socket

  ********************************************************************************************/
int socket(int domain, int type, int protocol)
{
	int i=0;
	struct Socket *socket = NULL;
	
	/* loop check socket list to find idle socket pointer */
	for(i=0; i<RIL_MAX_SOCKET_COUNT; i++)
    {
		if(_socketList[i] == NULL)
		{	break;	}
	}
	if(i == RIL_MAX_SOCKET_COUNT)
	{	return -28;	}		// ENOSPC
	
	/* alloc memory to fill socket info */
	socket = (struct Socket *)malloc(sizeof(struct Socket));
	if(socket == NULL)
	{	return -105;	}		// ENOSPC
	memset(socket, 0, sizeof(struct Socket));
	
	/* alloc memory to fill rx buffer or msglist */
	switch(type)
	{
		case SOCK_STREAM:
			socket->obj = malloc(sizeof(struct SocketStream));
			if(socket->obj == NULL)
			{	
				free(socket);
				return -105;	// ENOSPC
			}
			memset(socket->obj, 0, sizeof(struct SocketStream));
			break;
		case SOCK_DGRAM:
			socket->obj = malloc(sizeof(struct SocketDgRam));
			if(socket->obj == NULL)
			{	
				free(socket);
				return -105;	// ENOSPC
			}
			memset(socket->obj, 0, sizeof(struct SocketDgRam));
			break;
		case SOCK_RAW:
			break;
		default:
			free(socket);
			return -91;			// EPROTOTYPE
			
	}
	
	
	/* fill socket info */
	socket->id = i;
	socket->device = NULL;
	socket->type = type;
	
	_socketList[i] = socket;
	
    return i;
}
/*********************************************************************************************

  * @brief  closesocket
  * @param  s,  socket id
  * @return 0,  success
            <0, error code
  * @remark 

  ********************************************************************************************/
int closesocket(int s)
{
	struct Socket *socket = _socketList[s];

	RilDevice_Release(&_rilDevice, socket);
	
	free(_socketList[s]->obj);
	free(_socketList[s]);
	_socketList[s] = NULL;
	
	return 0;
}
/**********************************************************************************************/
// connect, tcp, connect to tcp server
/*********************************************************************************************/
int connect(int s, const struct sockaddr *name, socklen_t namelen)
{
	struct Socket *socket = _socketList[s];
	
	if(socket == NULL)
	{	return -2;	}		// ENOENT
	
	return RilDevice_Connect(&_rilDevice, socket, name, namelen);
}
int disconnect(int s)
{
	struct Socket *socket = _socketList[s];
	
	if(socket == NULL)
	{	return -2;	}		// ENOENT
	
	return RilDevice_Disconnect(&_rilDevice, socket);
}
/**********************************************************************************************/
//
/*********************************************************************************************/
int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
{}
/**********************************************************************************************/
// 
/*********************************************************************************************/
int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
{	return 0;	}
/**********************************************************************************************/
//
/*********************************************************************************************/
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{	return 0;	}
/**********************************************************************************************/
//
/*********************************************************************************************/
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{	return 0;	}
/**********************************************************************************************/
//
/*********************************************************************************************/
int listen(int s, int backlog)
{	return 0;	}
/**********************************************************************************************/
//
/*********************************************************************************************/
int recv(int s, void *mem, size_t size, int flags)
{
	struct Socket *socket = _socketList[s];
	
	if(socket == NULL)
	{	return -1;	}
	
	return RilDevice_Recv(&_rilDevice, socket, mem, size, flags);
}
/**********************************************************************************************/
//
/*********************************************************************************************/
int recvfrom(int s, void *mem, size_t size, int flags, struct sockaddr *from, socklen_t *fromlen)
{
	struct Socket *socket = _socketList[s];
	
	if(socket == NULL)
	{	return -2;	}		// ENOENT
	
	return RilDevice_RecvFrom(&_rilDevice, socket, (void *)mem, size, flags, from, fromlen);
}
/**********************************************************************************************/
// send , tcp, send packet to tcp server
/*********************************************************************************************/
int send(int s, const void *dataptr, size_t size, int flags)
{
	struct Socket *socket = _socketList[s];
	
	if(socket == NULL)
	{	return -2;	}		// ENOENT
	
	return RilDevice_Send(&_rilDevice, socket, (void *)dataptr, size, flags);
}
/**********************************************************************************************/
// sendto, UDP, send packet to specified udp address
/*********************************************************************************************/
int sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
{
	
	struct Socket *socket = _socketList[s];
	
	if(socket == NULL)
	{	return -2;	}		// ENOENT
	
	return RilDevice_SendTo(&_rilDevice, socket, (void *)dataptr, size, flags, to, tolen); 
}

/*********************************************************************************************

  ********************************************************************************************/
struct Socket* Ril_GetSocketById(int id)
{
	for(int i=0; i<RIL_MAX_SOCKET_COUNT; i++)
	{
		if(_socketList[i] != NULL)
		{
			if(_socketList[i]->id == id)
			{	return _socketList[i];	}
		}
	}
	
	return NULL;
}
